
#include "calllater.h"

void add_entry(delay_queue_t *delay_queue0,delay_entry_t *delay_entry0)
{
	delay_queue_reset(delay_queue0);
	if (delay_queue0->first_entry==NULL) //empty queue
	{
		printf("24\n");
		delay_queue0->first_entry=delay_entry0;
		delay_queue0->first_entry->prev=NULL;
		delay_queue0->first_entry->next=NULL;
	}
	else
	{
		while(delay_queue0->last_entry->next)
		{
			printf("25\n");
			delay_queue0->last_entry=delay_queue0->last_entry->next;
		}
		delay_queue0->last_entry->next=delay_entry0;
		delay_entry0->prev=delay_queue0->last_entry;
		delay_entry0->next=NULL;
	}
}

void del_entry(delay_queue_t *delay_queue0,delay_entry_t *delay_entry0)
{
	do{
		if (delay_entry0->prev==NULL && delay_entry0->next==NULL) //the head but the only one
		{
			free(delay_entry0);
			delay_queue0->first_entry=NULL;
			break;
		}
		if (delay_entry0->prev==NULL&&delay_entry0->next!=NULL) //for head,but not the last one
		{
			delay_queue0->first_entry=delay_entry0->next;
			delay_queue0->first_entry->prev=NULL;
			free(delay_entry0);
			break;
		}
		if(delay_entry0->prev!=NULL&&delay_entry0->next==NULL) //for tail,but not the last one
		{
			delay_entry0->prev->next=NULL;
			free(delay_entry0);
			break;
		}
		delay_entry0->prev->next=delay_entry0->next;
		delay_entry0->next->prev=delay_entry0->prev;
		free(delay_entry0);
	}while(0);
}

delay_queue_t * delay_queue_init()
{
	delay_queue_t *delay_queue0;
	delay_queue0=(delay_queue_t *)malloc(sizeof(delay_queue_t));
	if (delay_queue0==NULL) exit(0);
	delay_queue0->first_entry=NULL;
	delay_queue0->last_entry=NULL;
	return delay_queue0;
}

void delay_queue_destory(delay_queue_t *delay_queue0)
{
	if(delay_queue0==NULL) return;
	while(delay_queue0->first_entry)
	{
		del_entry(delay_queue0,delay_queue0->first_entry);
	}
	free(delay_queue0);
	delay_queue0=NULL;
}

void delay_queue_reset(delay_queue_t *delay_queue0)
{
	delay_queue0->last_entry = delay_queue0->first_entry;
}

void call_later(int seconds_to_delay,callback f_handler,void *client_data,delay_queue_t *delay_queue0)//client_data must malloc before call this function
{
	delay_entry_t *delay_entry0;
	delay_entry0=(delay_entry_t *)malloc(sizeof(delay_entry_t));
	if (delay_entry0==NULL) exit(0);
	delay_entry0->delay_handler=f_handler;
	delay_entry0->client_data=client_data;
	delay_entry0->seconds_to_delay=seconds_to_delay;
	delay_entry0->last_time=time(NULL);
	delay_entry0->next=NULL;
	delay_entry0->prev=NULL;
	if(delay_queue0 ==NULL)
		exit(0);
	add_entry(delay_queue0,delay_entry0);
}

int time_synchronize(delay_queue_t *delay_queue0)
{
	time_t now;
	delay_entry_t *delay_entry0;
	if(delay_queue0 == NULL)
	{
		printf("No difinition of queue\n");
		return -1;
	}
	delay_queue_reset(delay_queue0);
	while(delay_queue0->last_entry)
	{
		now=time(NULL);
		delay_entry0=delay_queue0->last_entry;
		if ((time_t)delay_entry0->seconds_to_delay+delay_entry0->last_time<now)//Time up
		{
			delay_entry0->delay_handler(delay_entry0->client_data);//execute
			delay_queue0->last_entry=delay_queue0->last_entry->next;//ignore it
			del_entry(delay_queue0,delay_entry0);
		}
		else
		{
			delay_queue0->last_entry=delay_queue0->last_entry->next;
		}
	}
	return 0;
}
